package cn.shujuhai.cms.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.shujuhai.cms.domain.*;
import cn.shujuhai.cms.mapper.InfoArticleMapper;
import cn.shujuhai.cms.mapper.SysChannelMapper;
import cn.shujuhai.cms.mapper.SysTemplateMapper;
import cn.shujuhai.cms.service.*;
import cn.shujuhai.cms.service.thymeleaf.StaticHtmlService;
import cn.shujuhai.cms.util.XssDetector;
import cn.shujuhai.common.pluging.data.ResultCode;
import cn.shujuhai.common.pluging.data.ResultVo;
import cn.shujuhai.common.pluging.file.FilesUtils;
import cn.shujuhai.workflow.service.ActDepartmentService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.mail.Folder;
import lombok.RequiredArgsConstructor;
import org.apache.tika.Tika;
import org.apache.tika.mime.MimeTypes;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: zhangDeZhong
 * @Date: 2024/12/5 12:01
 * @Description: 针对表【info_article(信息文章)】的数据库操作Service实现
 **/
@Service
@RequiredArgsConstructor
public class InfoArticleServiceImpl extends ServiceImpl<InfoArticleMapper, InfoArticle>
        implements InfoArticleService {

    private final InfoContentService infoContentService;
    private final InfoChannelService infoChannelService;
    private final StaticHtmlService staticHtmlService;
    private final SysChannelMapper sysChannelMapper;
    private final SysTemplateMapper sysTemplateMapper;
    private final ArticleParamService articleParamService;
    private final LogArticleService logArticleService;

    @Value("${template.static.resourceUrl}")
    public String UPLOAD_IMG_DIR;        //文章头图路径

    @Value("${template.static.attachmentUrl}")
    public String UPLOAD_ATTACHMENT_DIR; //文章附件路径

    @Value("${template.static.viewResourceUrl}")
    public String VIEW_IMG_DIR;        //文章头图访问路径

    @Value("${template.static.viewAttachmentUrl}")
    public String VIEW_ATTACHMENT_DIR; //文章附件访问路径

    @Value("${template.static.videoUrl}")
    public String UPLOAD_VIDEO_DIR; //文章视频路径

    @Value("${template.static.viewVideoUrl}")
    public String VIEW_VIDEO_DIR;        //文章视频访问路径

    final CacheManager cacheManager;

    /**
     * 根据栏目ID和分页查询参数获取文章列表
     *
     * @param channelId 栏目ID
     * @param title     搜索关键字（栏目标题）
     * @param pageNum   页码
     * @param pageSize  每页大小
     * @return 文章列表的分页结果
     */
    @Override
    public ResultVo<?> getArticlesByTitle(Long channelId, String title, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);


        List<InfoArticle> infoArticleList = this.getBaseMapper().getList(channelId, title);
        PageInfo<InfoArticle> pageInfo = new PageInfo<>(infoArticleList);
        return ResultVo.success(pageInfo);
    }

    /**
     * 添加文章信息
     *
     * @param infoArticle 文章信息
     * @return 结果信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> addArticle(InfoArticle infoArticle) {
        System.out.println("++++++++" + infoArticle);
        infoArticle.setCount(null);
        infoArticle.setStatus(null);
//        boolean xssAttack = XssDetector.isXssAttack(infoArticle.getContent());
//        if (xssAttack) {
//            return ResultVo.failure("检测到不安全内容，请修改后再提交");
//        }
        boolean saveInfo = this.save(infoArticle);
        if (!saveInfo) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        InfoContent infoContent = new InfoContent();
        infoContent.setContent(infoArticle.getContent().getBytes(StandardCharsets.UTF_8));
        infoContent.setArticleId(infoArticle.getArticleId());
        boolean saveContent = this.infoContentService.save(infoContent);
        if (saveContent) {
            List<Long> channelIds = infoArticle.getChannelIds();
            List<InfoChannel> infoChannels = new ArrayList<>();
            if (!channelIds.isEmpty()) {
                for (Long channelId : channelIds) {
                    InfoChannel infoChannel = new InfoChannel();
                    infoChannel.setArticleId(infoArticle.getArticleId());
                    infoChannel.setChannelId(channelId);
                    infoChannels.add(infoChannel);
                }
                boolean b = this.infoChannelService.saveBatch(infoChannels);
                if (!b) {
                    return ResultVo.failure(ResultCode.FAILED);
                }
            }

        }
        List<ArticleParam> articleParams = infoArticle.getInfoParam();
        for (ArticleParam articleParam : articleParams) {
            articleParam.setArticleId(infoArticle.getArticleId());
        }
        if (!this.articleParamService.saveBatch(articleParams)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }


    /**
     * 根据文章ID获取文章内容
     *
     * @param articleId 文章ID
     * @return 文章内容结果
     */
    @Override
    public ResultVo<?> getContentById(Long articleId) {
        InfoContent infoContent = this.infoContentService.getOne(Wrappers.<InfoContent>lambdaQuery().eq(InfoContent::getArticleId, articleId));
        return ResultVo.success(infoContent);
    }

    /**
     * 修改文章信息
     *
     * @param infoArticle 文章信息
     * @return 结果信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> updateArticle(InfoArticle infoArticle) {
        // 检查文章状态，已发布的文章不能修改
        if (infoArticle.getStatus() == 1 || infoArticle.getStatus() == 2) {
            return ResultVo.failure("文章已发布，不能修改");
        }

        // 清空某些字段，防止更新时被错误覆盖
        infoArticle.setCount(null);
        infoArticle.setStatus(null);

        // 更新文章基本信息
        boolean updateInfo = this.updateById(infoArticle);
        if (!updateInfo) {
            return ResultVo.failure(ResultCode.FAILED, "更新文章基本信息失败");
        }

        // 如果文章发布时间为空，更新发布时间为 null
        if (infoArticle.getPublishedTime() == null) {
            this.update(Wrappers.<InfoArticle>lambdaUpdate()
                    .set(InfoArticle::getPublishedTime, null)
                    .eq(InfoArticle::getArticleId, infoArticle.getArticleId()));
        }

        // 检查文章内容是否为空
        if (StrUtil.isEmpty(infoArticle.getContent())) {
            return ResultVo.success("文章内容为空，无需更新");
        }

        // 更新文章内容
        InfoContent infoContent = new InfoContent();
        infoContent.setContentId(infoArticle.getContentId());
        infoContent.setContent(infoArticle.getContent().getBytes(StandardCharsets.UTF_8));
        infoContent.setArticleId(infoArticle.getArticleId());
        boolean updateContent = this.infoContentService.updateById(infoContent);
        if (!updateContent) {
            return ResultVo.failure(ResultCode.FAILED, "更新文章内容失败");
        }

        // 删除旧的文章频道关系
        boolean removedChannels = infoChannelService.remove(Wrappers.<InfoChannel>lambdaQuery()
                .eq(InfoChannel::getArticleId, infoArticle.getArticleId()));
        if (!removedChannels) {
            return ResultVo.failure(ResultCode.FAILED, "删除旧的文章频道关系失败");
        }

        // 保存新的文章频道关系
        List<Long> channelIds = infoArticle.getChannelIds();
        if (channelIds != null && !channelIds.isEmpty()) {
            List<InfoChannel> infoChannels = channelIds.stream()
                    .map(channelId -> {
                        InfoChannel infoChannel = new InfoChannel();
                        infoChannel.setArticleId(infoArticle.getArticleId());
                        infoChannel.setChannelId(channelId);
                        return infoChannel;
                    })
                    .collect(Collectors.toList());

            boolean savedChannels = this.infoChannelService.saveBatch(infoChannels);
            if (!savedChannels) {
                return ResultVo.failure(ResultCode.FAILED, "保存新的文章频道关系失败");
            }
        }

        // 删除旧的文章参数信息
        List<ArticleParam> list = this.articleParamService.list(new QueryWrapper<ArticleParam>()
                .lambda().eq(ArticleParam::getArticleId, infoArticle.getArticleId()));
        if (!list.isEmpty()) {
            boolean removedParams = this.articleParamService.remove(new QueryWrapper<ArticleParam>()
                    .lambda().eq(ArticleParam::getArticleId, infoArticle.getArticleId()));
            if (!removedParams) {
                return ResultVo.failure(ResultCode.FAILED, "删除旧的文章参数信息失败");
            }
        }
        // 保存新的文章参数信息
        List<ArticleParam> articleParams = infoArticle.getInfoParam();
        if (articleParams != null && !articleParams.isEmpty()) {
            for (ArticleParam articleParam : articleParams) {
                articleParam.setArticleId(infoArticle.getArticleId());
            }
            boolean savedParams = this.articleParamService.saveBatch(articleParams);
            if (!savedParams) {
                return ResultVo.failure(ResultCode.FAILED, "保存新的文章参数信息失败");
            }
        }

        return ResultVo.success("文章更新成功");
    }

    /**
     * 根据文章ID删除文章信息
     *
     * @param articleId 文章ID
     * @return 结果信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> removeArticle(Long articleId) {
        Integer status = this.getById(articleId).getStatus();
        if (status == 1 || status == 2) {
            return ResultVo.failure("文章已发布，不能删除");
        }
        boolean removeContent = this.infoContentService.remove(Wrappers.<InfoContent>lambdaQuery().eq(InfoContent::getArticleId, articleId));
        this.infoChannelService.remove(Wrappers.<InfoChannel>lambdaQuery().eq(InfoChannel::getArticleId, articleId));
        this.articleParamService.remove(Wrappers.<ArticleParam>lambdaQuery().eq(ArticleParam::getArticleId, articleId));
        if (removeContent) {
            boolean remove = this.removeById(articleId);
            if (remove) {
                return ResultVo.success();
            }
        }
        return ResultVo.failure(ResultCode.ERROR);
    }

    /**
     * 根据文章ID列表批量删除文章信息
     *
     * @param articleIds 文章ID列表
     * @return 结果信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> removeBatchArticle(List<Long> articleIds) {
        List<InfoArticle> infoArticles = this.listByIds(articleIds);
        boolean hasStatus1Or2 = infoArticles.stream()
                .anyMatch(article -> article.getStatus() == 1 || article.getStatus() == 2);
        if (hasStatus1Or2) {
            return ResultVo.failure("文章已发布，不能修改");
        }
        boolean removeContent = this.infoContentService.remove(Wrappers.<InfoContent>lambdaQuery().in(InfoContent::getArticleId, articleIds));
        this.infoChannelService.remove(Wrappers.<InfoChannel>lambdaQuery().in(InfoChannel::getArticleId, articleIds));

        if (removeContent) {
            boolean removeBatchArticle = this.removeBatchByIds(articleIds);
            if (removeBatchArticle) {
                return ResultVo.success();
            }
        }
        return ResultVo.failure(ResultCode.ERROR);
    }

    /**
     * 修改文章发布状态信息
     *
     * @param articleId 文章ID
     * @param state     文章发布状态(待审核:0,审核通过:1,被驳回:2)
     * @return 结果信息
     */
    @Override
    public ResultVo<?> updateStatus(Long articleId, Integer state, String reason) {
        InfoArticle infoArticle = this.getById(articleId);
        if (articleId == null || state == null) {
            return ResultVo.failure(ResultCode.ERROR);
        }
        if (state == 1 && (infoArticle.getPublishedTime() == null || infoArticle.getPublishedTime().isBefore(LocalDateTime.now()))) {
            state = 2;
        }
        boolean update = this.update(Wrappers.<InfoArticle>lambdaUpdate()
                .set(InfoArticle::getStatus, state)
                .set(InfoArticle::getReason, reason)
                .set(state == 0, InfoArticle::getCount, 0)
                .eq(InfoArticle::getArticleId, articleId));
        if (update) {
            List<InfoChannel> infoChannels = this.infoChannelService.list(Wrappers.<InfoChannel>lambdaQuery().eq(InfoChannel::getArticleId, articleId));

            if (state == 2) {
                for (InfoChannel infoChannel : infoChannels) {
                    SysChannel sysChannel = this.sysChannelMapper.selectById(infoChannel.getChannelId());
                    SysTemplate sysTemplate = this.sysTemplateMapper.selectById(sysChannel.getDetailTemplate());
                    if (sysTemplate != null) {
                        this.staticHtmlService.articleStaticHtml(sysChannel, sysTemplate.getTemplateUrl(), infoArticle.getArticleId());
                    } else {
                        this.staticHtmlService.channelStaticHtml(sysChannel);
                    }
                }

            } else if (infoArticle.getStatus() == 2 && state == 0) {
                for (InfoChannel infoChannel : infoChannels) {
                    SysChannel sysChannel = this.sysChannelMapper.selectById(infoChannel.getChannelId());
                    this.staticHtmlService.deleteArticleStaticHtml(sysChannel, infoArticle.getArticleId());
                }

            }
            return ResultVo.success();
        } else {
            return ResultVo.failure(ResultCode.ERROR);
        }
    }

    /**
     * 发布待审核的文章
     */
    @Async("getAsyncExecutor")
    @Override
    public void doPendingArticles() {
        // 查询数据库中所有需要发布的文章，状态为待发布且发布时间小于当前时间
        List<InfoArticle> infoArticleList = this.list(Wrappers.<InfoArticle>lambdaQuery()
                .eq(InfoArticle::getStatus, 1)
                .le(InfoArticle::getPublishedTime, LocalDateTime.now()));
        List<Long> articleIds = infoArticleList.stream().map(InfoArticle::getArticleId).toList();
        if (!articleIds.isEmpty()) {
            this.update(Wrappers.<InfoArticle>lambdaUpdate()
                    .set(InfoArticle::getStatus, 2)
                    .in(InfoArticle::getArticleId, articleIds));
        }
        for (InfoArticle infoArticle : infoArticleList) {
            List<InfoChannel> infoChannels = this.infoChannelService.list(Wrappers.<InfoChannel>lambdaQuery().eq(InfoChannel::getArticleId, infoArticle.getArticleId()));
            for (InfoChannel infoChannel : infoChannels) {
                SysChannel sysChannel = this.sysChannelMapper.selectById(infoChannel.getChannelId());
                SysTemplate sysTemplate = this.sysTemplateMapper.selectById(sysChannel.getDetailTemplate());
                if (sysTemplate != null) {
                    this.staticHtmlService.articleStaticHtml(sysChannel, sysTemplate.getTemplateUrl(), infoArticle.getArticleId());
                }
            }

        }
    }

    /**
     * 根据栏目ID获取文章列表
     *
     * @param channelId 栏目ID
     * @return 文章列表结果信息
     */
    @Override
    public ResultVo<?> getArticlesByChannelId(Long channelId) {
        List<InfoArticle> infoArticleList = this.list(Wrappers.<InfoArticle>lambdaQuery().eq(InfoArticle::getChannelId, channelId)
                .eq(InfoArticle::getStatus, 2));
        return ResultVo.success(infoArticleList);
    }

    @Override
    public ResultVo<?> search_list(String search, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);


        List<InfoArticle> infoArticleList = this.getBaseMapper().search_list(search);
        PageInfo<InfoArticle> pageInfo = new PageInfo<>(infoArticleList);
        return ResultVo.success(pageInfo);
    }


    @Override
    public void countArticleNum(Map<String, String> body) {
        String pageUrl = body.get("pageUrl");
        String zhArticle = "/article/zh-CN/";
        String enArticle = "/article/en/";
        String k = "";
        if (pageUrl.contains(zhArticle)) {
            k = zhArticle;
        } else if (pageUrl.contains(enArticle)) {
            k = enArticle;
        }
        if (k.isEmpty()) {
            return;
        }
        String urlKey = pageUrl.split(k)[1].split(".html")[0].split("/")[0];
        Long articleId = Long.valueOf(pageUrl.split(k)[1].split(".html")[0].split("/")[1]);


        this.sysChannelMapper.update(Wrappers.<SysChannel>lambdaUpdate()
                .eq(SysChannel::getUrlKey, urlKey)
                .setSql("count = count + 1"));


        this.update(Wrappers.<InfoArticle>lambdaUpdate()
                .eq(InfoArticle::getArticleId, articleId)
                .setSql("count = count + 1"));
    }

    @Override
    public ResultVo<?> viewArticleRanking() {
        List<InfoArticle> list = this.list(Wrappers.<InfoArticle>lambdaQuery()
                .select(InfoArticle::getTitle, InfoArticle::getCount)
                .eq(InfoArticle::getStatus, 2)
                .orderByDesc(InfoArticle::getCount)
                .orderByDesc(InfoArticle::getPublishedTime)
                .last("limit 10"));
        return ResultVo.success(list);
    }

    @Override
    public ResultVo<?> getCountArticle(String date) {
        if (date == null || date.isEmpty()) {
            // 如果没有传递日期范围，从 sys_channel 表中查询访问量前10的栏目
            List<InfoArticle> list = this.list(new QueryWrapper<InfoArticle>().orderByDesc("count").last("LIMIT 10"));
            return ResultVo.success(list);
        } else {
            // 解析日期范围
            String[] dates = date.split(" - ");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime startDate = LocalDateTime.parse(dates[0], formatter);
            LocalDateTime endDate = LocalDateTime.parse(dates[1], formatter);

            // 根据日期范围筛选并统计每个栏目的访问量
            QueryWrapper<LogArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.ge("systime", startDate)
                    .le("systime", endDate);
            List<LogArticle> logArticles = this.logArticleService.list(queryWrapper);

            // 使用 Java 8 的流（Stream）来统计每个栏目的访问次数
            List<ArticleVisitStatistics> statisticsList = logArticles.stream()
                    .collect(Collectors.groupingBy(
                            LogArticle::getArticleId,
                            Collectors.summingInt(logArticle -> 1)
                    )).entrySet().stream().map(entry -> {
                        ArticleVisitStatistics statistics = new ArticleVisitStatistics();
                        statistics.setArticleId(entry.getKey());
                        statistics.setTitle(this.getArticleTitleById(entry.getKey()));
                        statistics.setCount(entry.getValue());
                        return statistics;
                    }).sorted((s1, s2) -> s2.getCount().compareTo(s1.getCount())) // 按访问量降序排序
                    .limit(10) // 限制返回的数量为10个
                    .collect(Collectors.toList());

            return ResultVo.success(statisticsList);
        }
    }

    public String getArticleTitleById(Long articleId) {
        InfoArticle infoArticle = this.getOne(new QueryWrapper<InfoArticle>().lambda().select(InfoArticle::getTitle).eq(InfoArticle::getArticleId, articleId
        ));
        return infoArticle.getTitle();
    }

    /**
     * 文章头图上传
     *
     * @param file 文件内容
     * @return 结果信息
     */
    @Override
    public ResultVo<?> uploadImg(MultipartFile file) {
        try {
            // 校验文件类型
            String fileName = file.getOriginalFilename();
            if (fileName == null || !fileName.matches("^(?i).*(\\.jpg|\\.png|\\.webp)$")) {
                return ResultVo.failure("仅支持上传webp、jpg 和 png 格式的图片");
            }

            // 创建临时文件
            File tempFile = File.createTempFile("upload-", fileName);
            tempFile.deleteOnExit();
            Path tempFilePath = tempFile.toPath();

            // 将上传的文件内容复制到临时文件
            Files.copy(file.getInputStream(), tempFilePath, StandardCopyOption.REPLACE_EXISTING);

            // 校验文件 MIME 类型
            String mimeType = Files.probeContentType(tempFilePath);
            if (!Arrays.asList("image/jpeg", "image/png", "image/webp").contains(mimeType)) {
                return ResultVo.failure("文件格式不支持");
            }

            // 校验文件大小
            Cache cache = cacheManager.getCache("sys_setting");
            if (cache == null) {
                throw new IllegalStateException("未获取到缓存");
            }
            String imageSize = cache.get("ARTICLE_RESOURCE", String.class);
            imageSize = StrUtil.trim(imageSize);
            int imageMaxSize = StrUtil.isNotEmpty(imageSize) ? Integer.parseInt(imageSize) : 2048;
            if (file.getSize() > imageMaxSize * 1024L) {
                return ResultVo.failure("图片大小不能超过 " + imageMaxSize + "KB");
            }

            // 上传文件
            String uploadedFile = FilesUtils.uploadFile(file, UPLOAD_IMG_DIR, VIEW_IMG_DIR);
            return ResultVo.success(uploadedFile);
        } catch (IOException e) {
            return ResultVo.failure("文件上传失败: " + e.getMessage());
        } catch (RuntimeException e) {
            return ResultVo.failure(e.getMessage());
        }
    }

    /**
     * 文章附件上传
     *
     * @param file 文件内容
     * @return 结果信息
     */
    @Override
    public ResultVo<?> uploadAttachment(MultipartFile file) {
        try {
            // 校验文件类型
            String fileName = file.getOriginalFilename();
            if (fileName == null || !fileName.matches("^(?i).*(\\.zip|\\.rar|\\.pdf|\\.xlsx|\\.doc|\\.docx)$")) {
                return ResultVo.failure("仅支持上传的文件格式为zip, rar, pdf, xlsx, doc, docx");
            }

            // 使用 Tika 检测文件 MIME 类型
            MimeTypes mimeTypes = MimeTypes.getDefaultMimeTypes();
            Tika tika = new Tika();
            String mimeType;
            try (InputStream inputStream = file.getInputStream()) {
                // 使用 Tika 检测 MIME 类型
                mimeType = tika.detect(inputStream);
                if (!Arrays.asList(
                        "application/zip",
                        "application/x-rar-compressed",
                        "application/pdf",
                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                        "application/msword",
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                ).contains(mimeType)) {
                    return ResultVo.failure("文件格式不支持");
                }
            } catch (IOException e) {
                return ResultVo.failure("文件类型检测失败: " + e.getMessage());
            }

            // 校验文件大小
            Cache cache = cacheManager.getCache("sys_setting");
            if (cache == null) {
                throw new IllegalStateException("未获取到缓存");
            }
            String size = cache.get("ARTICLE_ATTACHMENT", String.class);
            size = StrUtil.trim(size);
            int maxSize = StrUtil.isNotEmpty(size) ? Integer.parseInt(size) : 2048;
            if (file.getSize() > maxSize * 1024L) {
                return ResultVo.failure("文件大小不能超过 " + maxSize + "KB");
            }

            // 上传文件
            String uploadedFile = FilesUtils.uploadFile(file, UPLOAD_ATTACHMENT_DIR, VIEW_ATTACHMENT_DIR);
            return ResultVo.success(uploadedFile);
        } catch (RuntimeException e) {
            e.printStackTrace(); // 打印详细的错误堆栈
            return ResultVo.failure(e.getMessage());
        }
    }

    /**
     * 视频文件上传
     *
     * @param file 文件内容
     * @return 结果信息
     */
    @Override
    public ResultVo<?> uploadVideo(MultipartFile file) {
        try {
            // 校验文件类型，支持的视频格式
            String fileName = file.getOriginalFilename();
            if (fileName == null || !fileName.matches("^(?i).*(\\.mp4|\\.webm|\\.ogg)$")) {
                return ResultVo.failure("仅支持上传视频文件 (.mp4, .webm, .ogg)");
            }

            // 创建临时文件
            File tempFile = File.createTempFile("upload-", fileName);
            tempFile.deleteOnExit();
            Path tempFilePath = tempFile.toPath();

            // 将上传的文件内容复制到临时文件
            Files.copy(file.getInputStream(), tempFilePath, StandardCopyOption.REPLACE_EXISTING);

            // 校验文件 MIME 类型
            String mimeType = Files.probeContentType(tempFilePath);
            if (!Arrays.asList(
                    "video/mp4",
                    "video/webm",
                    "video/ogg"
            ).contains(mimeType)) {
                return ResultVo.failure("文件格式不支持");
            }

            // 校验文件大小
            long maxSize = 50 * 1024 * 1024; // 50MB
            if (file.getSize() > maxSize) {
                return ResultVo.failure("文件大小不能超过 50MB");
            }

            // 上传文件
            String uploadedFile = FilesUtils.uploadFile(file, UPLOAD_VIDEO_DIR, VIEW_VIDEO_DIR);
            return ResultVo.success(uploadedFile);
        } catch (RuntimeException e) {
            return ResultVo.failure(e.getMessage());
        } catch (IOException e) {
            return ResultVo.failure("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 获得文章浏览量总和
     *
     * @return 文章浏览量信息结果
     */
    @Override
    public ResultVo<?> getTotalViewCount() {
        // 通过流处理将查询结果转换为Integer类型，并计算总和
        Integer totalViewCount = this.baseMapper.selectObjs(Wrappers.<InfoArticle>lambdaQuery().select(InfoArticle::getCount))
                .stream()
                .mapToInt(count -> Math.toIntExact((Long) count))
                .sum();
        // 返回成功结果，包含总浏览量
        return ResultVo.success(totalViewCount);

    }

    /**
     * 根据文章ID获取文章信息
     *
     * @param articleId 文章ID
     * @return 文章信息结果
     */
    @Override
    public ResultVo<?> getInfoById(Long articleId) {
        return ResultVo.success(this.getById(articleId));
    }


}




